package org.SimpleSpringBoot.web;



import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpsServer;
import org.SimpleSpringBoot.annotation.Controller;
import org.SimpleSpringBoot.container.ApplicationContext;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;


/**
 * 简单的web服务器实现
 */
public class SimpleWebServer {




    private final ApplicationContext applicationContext;

    private final Map<String,HandlerMethod> handlerMethods=new HashMap<>();

    private HttpsServer server;


    public SimpleWebServer(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }


    /**
     * 启动web服务
     */
    public void start(int port)throws IOException{
        //扫描和注册处理器方法
        scanHandlerMethods();

        //创建Http服务器
        server = HttpsServer.create(new InetSocketAddress(port), 0);

        //注册处理器
        for (Map.Entry<String,HandlerMethod> entry:handlerMethods.entrySet()){
            server.createContext(entry.getKey(),new HandlerMethod.RequestHandler(entry.getValue()));  //todo
        }
        //启动服务器
        server.start();
        System.out.println("web服务器启动成功，请访问地址： http://127.0.0.1:"+port);
    }

    /**
     *停止web服务器
     */
    public void stop(){
        if (server!=null){
            server.stop(0);
            System.out.println("web服务器已经停止");
        }
    }

    /**
     * 扫描处理器方法
     */
    private void scanHandlerMethods(){
        for (String beanName:applicationContext.getBeanFactory().getAllBeanDefinitions().keySet()){
            Object bean = applicationContext.getBean(beanName);
            Class<?> beanClass = bean.getClass();

            //检查是否为Controller
            if (beanClass.isAnnotationPresent(RestController.class)||beanClass.isAnnotationPresent(Controller.class)){
                //扫描方法
                for (Method method:beanClass.getDeclaredMethods()){
                    if (method.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping mapping = method.getAnnotation(RequestMapping.class);
                        String path = mapping.value();
                        if (path.isEmpty()&&mapping.path().length>0){
                            path=mapping.path()[0];
                        }

                        handlerMethods.put(path,new HandlerMethod(bean,method));
                        System.out.println("注册处理器方法"+path+"-->"+method.getName());

                    }

                }
            }
        }
    }


/**
 * 处理器方法包装类
 */
private static class HandlerMethod{
    private final Object bean;

    private final Method method;


    private HandlerMethod(Object bean, Method method) {
        this.bean = bean;
        this.method = method;
    }
    public Object getBean(){
        return bean;
    }
    public Method getMethod(){
        return method;
    }
/**
 * HTTP请求处理器
 */
private static class RequestHandler implements HttpHandler{
    private final HandlerMethod handlerMethod;

    private RequestHandler(HandlerMethod handlerMethod) {
        this.handlerMethod = handlerMethod;
    }
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        try {
            //调用处理器方法
            Object result = handlerMethod.getMethod().invoke(handlerMethod.getBean());

            //返回响应
            String response = result == null ? result.toString() : "OK";
            exchange.getRequestHeaders().set("Content-Type","text/plain; charset=UTF-8");
            exchange.sendResponseHeaders(200,response.getBytes("UTF-8").length);
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes("UTF-8"));
            os.close();
        }catch (Exception e){
            String errorResponse="Internal SServer Error:"+e.getMessage();
            exchange.sendResponseHeaders(500,errorResponse.getBytes("UTF-8").length);
            OutputStream os = exchange.getResponseBody();
            os.write(errorResponse.getBytes("UTF-8"));
            os.close();
        }


    }
}


}





}
